package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
import cn.iocoder.yudao.module.bpm.message.ProcessInstanceMessage;
import cn.iocoder.yudao.module.bpm.message.ProcessTaskMessage;
import cn.iocoder.yudao.module.bpm.message.dto.BpmProcessTaskAssignedMessage;
import cn.iocoder.yudao.module.bpm.message.dto.BpmProcessTaskCancelledMessage;
import cn.iocoder.yudao.module.bpm.message.dto.BpmProcessTaskCompletedMessage;
import cn.iocoder.yudao.module.bpm.message.dto.BpmProcessTaskCreatedMessage;
import cn.iocoder.yudao.module.bpm.service.task.BpmActivityService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
import com.google.common.collect.ImmutableSet;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
import org.flowable.engine.delegate.event.FlowableActivityCancelledEvent;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;

/**
 * 监听 {@link Task} 的开始与完成
 *
 * @author jason
 */
@Component
@Slf4j
public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {

    @Resource
    @Lazy // 解决循环依赖
    private BpmTaskService taskService;
    @Resource
    @Lazy // 解决循环依赖
    private BpmActivityService activityService;
//    @Resource
//    @Lazy // 解决循环依赖
//    private BpmProcessTaskEventPublisher processTaskEventPublisher;
    @Resource
    @Lazy
    private BpmProcessInstanceService processInstanceService;

    @Resource
    @Lazy
    private ProcessTaskMessage processTaskMessage;
    @Resource
    @Lazy
    private ProcessInstanceMessage processInstanceMessage;

    public static final Set<FlowableEngineEventType> TASK_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
            .add(FlowableEngineEventType.TASK_CREATED)
            .add(FlowableEngineEventType.TASK_ASSIGNED)
            .add(FlowableEngineEventType.TASK_COMPLETED) // 由于审批通过时，已经记录了 task 的 status 为通过，所以不需要监听了。
            .add(FlowableEngineEventType.ACTIVITY_CANCELLED)
            .build();

    public BpmTaskEventListener(){
        super(TASK_EVENTS);
    }

    @Override
    protected void taskCreated(FlowableEngineEntityEvent event) {
        Task task = (Task) event.getEntity();
        taskService.updateTaskStatusWhenCreated(task);
        ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
        BpmProcessTaskCreatedMessage bpmProcessTaskCreatedMessage = new BpmProcessTaskCreatedMessage()
                .setProcessId(task.getProcessInstanceId())
                .setProcessDefinitionKey(processInstance.getProcessDefinitionKey())
                .setProcessName(processInstance.getName())
                .setTaskId(task.getId())
                .setTaskDefinitionKey(task.getTaskDefinitionKey())
                .setStatus(BpmTaskStatusEnum.RUNNING)
                .setBusinessKey(processInstance.getBusinessKey())
                .setAssignee(task.getAssignee())
                ;
        // 发送消息提醒
        processTaskMessage.onProcessInstanceTaskCreatedMsg(bpmProcessTaskCreatedMessage);
    }

    @Override
    protected void taskAssigned(FlowableEngineEntityEvent event) {
        Task task = (Task) event.getEntity();
        taskService.updateTaskExtAssign(task);

        ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
        BpmProcessTaskAssignedMessage bpmProcessTaskAssignedMessage = new BpmProcessTaskAssignedMessage()
                .setProcessId(task.getProcessInstanceId())
                .setProcessDefinitionKey(processInstance.getProcessDefinitionKey())
                .setProcessName(processInstance.getName())
                .setTaskId(task.getId())
                .setTaskDefinitionKey(task.getTaskDefinitionKey())
                .setStatus(BpmTaskStatusEnum.RUNNING)
                .setBusinessKey(processInstance.getBusinessKey())
                .setAssignee(task.getAssignee())
                ;
        // 发送消息提醒
        processTaskMessage.onProcessInstanceTaskAssignedMsg(bpmProcessTaskAssignedMessage);

    }

    @Override
    protected void activityCancelled(FlowableActivityCancelledEvent event) {
        List<HistoricActivityInstance> activityList = activityService.getHistoricActivityListByExecutionId(event.getExecutionId());
        if (CollUtil.isEmpty(activityList)) {
            log.error("[activityCancelled][使用 executionId({}) 查找不到对应的活动实例]", event.getExecutionId());
            return;
        }
        // 遍历处理
        ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getProcessInstanceId());
        activityList.forEach(activity -> {
            if (StrUtil.isEmpty(activity.getTaskId())) {
                return;
            }
            taskService.updateTaskStatusWhenCanceled(activity.getTaskId());

            Task task = taskService.getTask(activity.getTaskId());
            if(null == task){
                return;
            }

            BpmProcessTaskCancelledMessage bpmProcessTaskCancelledMessage = new BpmProcessTaskCancelledMessage()
                    .setProcessId(task.getProcessInstanceId())
                    .setProcessDefinitionKey(processInstance.getProcessDefinitionKey())
                    .setProcessName(processInstance.getName())
                    .setTaskId(task.getId())
                    .setTaskDefinitionKey(task.getTaskDefinitionKey())
                    .setStatus(BpmTaskStatusEnum.RUNNING)
                    .setBusinessKey(processInstance.getBusinessKey())
                    .setAssignee(task.getAssignee())
                    ;
            // 发送消息提醒
            processTaskMessage.onProcessInstanceTaskCleanMsg(bpmProcessTaskCancelledMessage);

        });
    }


    @Override
    protected void taskCompleted(FlowableEngineEntityEvent event) {
        Task task = (Task) event.getEntity();

        ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
        BpmProcessTaskCompletedMessage bpmProcessTaskCompletedMessage = new BpmProcessTaskCompletedMessage()
                .setProcessId(task.getProcessInstanceId())
                .setProcessDefinitionKey(processInstance.getProcessDefinitionKey())
                .setProcessName(processInstance.getName())
                .setTaskId(task.getId())
                .setTaskDefinitionKey(task.getTaskDefinitionKey())
                .setStatus(BpmTaskStatusEnum.RUNNING)
                .setBusinessKey(processInstance.getBusinessKey())
                .setAssignee(task.getAssignee())
                ;
        // 发送消息提醒
        processTaskMessage.onProcessInstanceTaskFinishedMsg(bpmProcessTaskCompletedMessage);

    }

}
